package com.googlecode.slm.log;

import java.lang.reflect.Constructor;

import org.apache.ibatis.io.Resources;

public class LogFactory {

	private static Constructor<? extends Log> logConstructor;

	static {
		tryImplementation(new Runnable() {
			public void run() {
				useLog4JLog();
			}
		});
		tryImplementation(new Runnable() {
			public void run() {
				useNoLog();
			}
		});
		tryImplementation(new Runnable() {
			public void run() {
				useSystemLog();
			}
		});
	}

	public static Log getLog(Class<?> aClass) {
		try {
			return logConstructor.newInstance(new Object[] { aClass });
		} catch (Throwable t) {
			throw new RuntimeException("Error creating logger for class " + aClass + ".  Cause: " + t, t);
		}
	}



	public static synchronized void useLog4JLog() {
		setImplementation("com.googlecode.slm.log.Log4jLog");
	}

	public static synchronized void useSystemLog() {
		setImplementation("com.googlecode.slm.log.SystemLog");
	}

	public static synchronized void useNoLog() {
		setImplementation("com.googlecode.slm.log.NoLog");
	}

	private static void tryImplementation(Runnable runnable) {
		if (logConstructor == null) {
			try {
				runnable.run();
			} catch (Throwable t) {
				
			}
		}
	}

	private static void setImplementation(String implClassName) {
		try {
			@SuppressWarnings("unchecked")
			Class<? extends Log> implClass = (Class<? extends Log>) Resources
					.classForName(implClassName);
			Constructor<? extends Log> candidate = implClass
					.getConstructor(new Class[] { Class.class });
			Log log = candidate.newInstance(new Object[] { LogFactory.class });
			log.debug("Logging initialized using '" + implClassName
					+ "' adapter.");
			logConstructor = candidate;
		} catch (Throwable t) {
			throw new RuntimeException(
					"Error setting Log implementation.  Cause: " + t, t);
		}
	}

}
